<?php

declare(strict_types=1);

namespace app\eslib;

/**
 * 日历 助手类
 * @version 1.0.0
 */
class EsCalendar
{

    const CN_WEEKDAYS = ['一', '二', '三', '四', '五', '六', '日'];

    public function __construct()
    {
    }
    /**
     * 获取样式
     */
    public static function getStyle()
    {
        return '<style>.week{color:#999}.holiday{color:#090}.invalid{color:#CCC}</style>';
    }
    /**
     * 获取月历数据
     */
    public function getMonthCalendar(int $year, int $month)
    {
        $dateYm = $year . '-' . $month;
        $timestampFirstDay = strtotime("{$dateYm}-1");
        // 本月有几天
        $lastDay = date('t', $timestampFirstDay);
        // 本月的第一天是第几周
        $week = intval(date('W', $timestampFirstDay));
        // 本月第一天是星期几（0 表示 Sunday[星期日]，6 表示 Saturday[星期六]）
        $weekDay = date('w', $timestampFirstDay);
        if ($weekDay == 0) {
            $weekDay = 7;
        }
        $iWeekDay = 1;
        $n = $weekDay;
        $weekDays = [];
        // 补全上个月过渡日期
        if ($weekDay > 0) {
            $weekDay--;
            // 上月
            $prevMonth = date('Y-m', strtotime('-1 month', $timestampFirstDay));
            // 上月有几天
            $lastDayOfPrevMonth = date('t', strtotime($prevMonth . '-1'));
            while ($weekDay > 0) {
                $day = $lastDayOfPrevMonth - $weekDay + 1;
                $weekDays[$week][] = ['day' => $day, 'date' => "{$prevMonth}-{$day}", 'status' => false, 'is_holiday' => $iWeekDay > 5];
                $weekDay--;
                $iWeekDay++;
            }
        }
        // 填充日历
        for ($day = 1; $day <= $lastDay; $day++) {
            $weekDays[$week][] = ['day' => $day, 'status' => true, 'date' => "{$dateYm}-{$day}", 'is_holiday' => $iWeekDay > 5];
            if ($n % 7 == 0) {
                $week++;
                $iWeekDay = 0;
            }
            $iWeekDay++;
            $n++;
        }
        // 本月最后一天星期几
        $weekDay = date('w', strtotime("{$dateYm}-{$lastDay}"));
        if ($weekDay == 0) {
            $weekDay = 7;
        }
        if ($weekDay < 7) {
            $weekDay = 7 - $weekDay;
            // 下月
            $nextMonth = date('Y-m', strtotime('1 month', $timestampFirstDay));
            for ($i = 1; $i <= $weekDay; $i++) {
                $weekDays[$week][] = ['day' => $i, 'date' => "{$nextMonth}-{$i}", 'status' => false, 'is_holiday' => $iWeekDay > 5];
                $iWeekDay++;
            }
        }
        return $weekDays;
    }
    /**
     * 打印月历
     */
    public function printMonthCalendar(int $year, int $month)
    {
        $cnWeeks = self::CN_WEEKDAYS;
        echo '<h5>', $month, '月</h5>';
        echo '<table border="1"><tr><td>#</td>';
        $i = 1;
        foreach ($cnWeeks as $week) {
            echo '<td', ($i > 5 ? ' class="holiday"' : ''), '>星期', $week, '</td>';
            $i++;
        }
        echo '</tr>';
        $style = '';
        $weekDays = $this->getMonthCalendar($year, $month);
        foreach ($weekDays as $week => $days) {
            echo '<tr><td class="week">', $week, '</td>';
            $i = 1;
            foreach ($days as $dayInfo) {
                $style = '';
                if ($i > 5) {
                    $style = ' class="holiday"';
                }
                if (!$dayInfo['status']) {
                    $style = ' class="invalid"';
                }
                echo '<td', $style, ' title="', $dayInfo['date'], '">', $dayInfo['day'], '</td>';
                $i++;
            }
            echo '</tr>';
        }
        echo '</table>';
    }
}
